﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace cs_utilities.error
{
    public class error_handler
    {
        private static error_handler _instance = null;

        string _appname = null;

        //---------------------------------------------------------------------------
        public static error_handler set_instance(string appname)
        {
            _instance = new error_handler(appname);
            return _instance;
        }
        //---------------------------------------------------------------------------
        public static error_handler get_instance()
        {
            return _instance;
        }
        //---------------------------------------------------------------------------
        private error_handler(string appname)
        {
            this._appname = appname;
        }
        //---------------------------------------------------------------------------
        public string generate_error_msg(string functionName, Exception e)
        {
            return generate_error_msg(functionName, e, null);
        }
        //---------------------------------------------------------------------------
        /// <summary>
        /// Function generates an error message, and returns it.
        /// </summary>
        public string generate_error_msg(string functionName, Exception e, string custom_message)
        {
            string err = "---------------------------------------------------------------------------\r\n";
            err += "                      " + _appname + " Exception\r\n";
            err += e.GetType().ToString() + " In " + functionName + "()\r\n";

            if (e.GetType() == typeof(COMException))
            {
                err += "Error Code: 0x" + ((COMException)e).ErrorCode.ToString("x") + "\r\n";
            }

            err += "Exception Message: " + e.Message + "\r\n";

            Exception inner = e.InnerException;
            while (inner != null)
            {
                err += "Inner Exception Message: " + inner.Message + "\r\n";
                inner = inner.InnerException;
            }

            if (custom_message != null && custom_message != "")
            {
                err += "Custom Message: " + custom_message + "\r\n";
            }

            err += "Stack Trace:\r\n" + e.StackTrace;
            err += "\r\n---------------------------------------------------------------------------\r\n";

            return err;
        }
        //---------------------------------------------------------------------------
        public string trace_exception(string function_name, Exception e)
        {
            return trace_exception(function_name, e, null);
        }
        //---------------------------------------------------------------------------
        public string trace_exception(string function_name, Exception e, string custom_message)
        {
            string msg = generate_error_msg(function_name, e, custom_message);
            Trace.WriteLine(msg);
            return msg;
        }
        //---------------------------------------------------------------------------
        /// <summary>
        /// Traces the exception and logs it to the event viewer.
        /// Notice: if event log does not exist, one will be created!
        /// </summary>
        public string log_exception(string function_name, Exception e)
        {
            return log_exception(function_name, e, null);
        }
        //---------------------------------------------------------------------------
        /// <summary>
        /// Traces the exception and logs it to the event viewer.
        /// Failed to log will display the error in the debug view.
        /// 
        /// Notice: if event log does not exist, one will be created!
        /// </summary>
        public string log_exception(string function_name, Exception e, string custom_message)
        {
            string msg = generate_error_msg(function_name, e, custom_message);

            try
            {
                // trace error
                Trace.WriteLine(msg);
                // log to event viewer

                if (!EventLog.SourceExists(_appname))
                    EventLog.CreateEventSource(_appname, "Application");

                EventLog aLog = new EventLog("Application", ".", _appname);

                if (aLog.OverflowAction != OverflowAction.OverwriteAsNeeded)
                {
                    try
                    {
                        aLog.ModifyOverflowPolicy(OverflowAction.OverwriteAsNeeded, 3);
                    }
                    catch
                    {
                        // Trace.WriteLine(string.Format("EventLog policy is {0}, and cannot be changed to {1}", aLog.OverflowAction.ToString(), OverflowAction.OverwriteAsNeeded.ToString()));
                    }
                }

                aLog.WriteEntry(msg, EventLogEntryType.Error);
            }
            catch (Exception exp)
            {
                Trace.WriteLine(_appname + ": Failed logging to event viewer: " + exp.GetType().Name + "\r\n" + exp.Message);
            }

            return msg;
        }
        //---------------------------------------------------------------------------
    }
}